"""
设想的API骨架代码模块
"""
import os
import warnings
from copy import deepcopy

from dotenv import load_dotenv, find_dotenv
from .query import Query
import pandas as pd


class DemoAPI:
    """
    API demo.
    该类主要实现与用户的交互，包括：
    - 接收并校验参数，防止SQL注入等
    - 根据需求解析为数据库接口可使用的参数
    - 对返回值进行规范化处理，最终返回给用户统一的数据结构
    - 进行异常处理，包括服务端和接口端，考虑是否统一为错误代码

    目前只有一个get_demo_data方法，
    设想后期加入各模块独立的方法，如get_xxx_data

    get_demo_data(
        database = 'VnTrader_Daily_Db',
        collection = 'MAINFUTURE',
        query = {'exchangeCode': 'CFE'},
        output = 'pd'  # pd.DataFrame对象
    )

    """

    def __init__(self):
        # 检查.env文件是否存在
        try:
            load_dotenv(find_dotenv(raise_error_if_not_found=True,
                                    usecwd=True), override=True)
        except IOError:
            # 未设置.env文件则给出提醒，不中断程序
            warnings.warn('.env file not found')

        # 环境变量无法读取的，使用默认连接信息（本地，无用户）
        self.client_settings = dict(
            # 解析mongo环境变量
            mongo_host=os.getenv('MONGO_HOST', 'localhost'),
            mongo_port=os.getenv('MONGO_PORT', '27017'),
            mongo_user=os.getenv('MONGO_USER'),
            mongo_passwd=os.getenv('MONGO_PASSWD'),

            # 解析mysql环境变量
            mysql_host=os.getenv('MYSQL_HOST', 'localhost'),
            mysql_port=os.getenv('MYSQL_PORT', '3306'),
            mysql_user=os.getenv('MYSQL_USER', 'root'),
            mysql_passwd=os.getenv('MYSQL_PASSWD', '')
        )

        self.query = Query(self.client_settings)

    def get_demo_data(self, **kwargs):
        """面向用户的接口, 根据需求设计具体参数字段"""
        # 标记当前方法名
        kwargs['method_called'] = 'get_demo_data'

        # todo:根据可能出现的错误类型，返回错误码，需设计。
        # todo:考虑将异常处理代码分入各模块更清晰，暂时统一放这里
        # -----------------------------------
        try:  # 考虑：统一处理解析模块异常
            # 用户输入校验与解析
            request = self._parse_request(kwargs)
        except Exception as e:
            print(f'解析模块出现了错误{e}')
            raise Exception(e)

        # ------------------------------------
        try:  # 考虑：统一处理数据规范化模块异常
            # 统一内部接口读取数据
            data = self._get_data(request)
        except Exception as e:
            print(f'读取模块出现了错误{e}')
            raise Exception(e)

        # -------------------------------------
        try:  # 考虑：统一处理数据规范化模块异常
            # 对数据进行规范化处理
            data = self._process_data(data, request)
        except Exception as e:
            print(f'规范化模块出现了错误{e}')
            raise Exception(e)

        return data

    def _parse_request(self, kwargs):
        """校验用户输入，并解析需求（未实现），有误的返回异常"""
        # TODO：解析传入的需求字符串,或者另起一类封装需求对象

        request = deepcopy(kwargs)
        if request['method_called'] == 'get_demo_data':
            request['client'] = 'mongo'

        return request

    def _get_data(self, request):
        """利用Query类查找数据，可考虑在此处理异常"""
        return self.query.retrieve(request)

    def _process_data(self, data, request):
        """对API返回值做规范化处理"""
        # TODO:对读取的数据进行处理，返回最终的数据
        if request['output'] == 'pd':
            return pd.DataFrame(list(data))
        else:
            return list(data)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.query.close()
